import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
from sklearn.decomposition import PCA
from sklearn import decomposition
from sklearn.preprocessing import StandardScaler
from sklearn import preprocessing
df=pd.read_excel('/content/base_a_traiter.xlsx')
df = pd.read_excel('C:\\Users\\elisa\\OneDrive - GENES\\Documents\\GitHub\\Projet-Python-pour-le-Data-Scientist\\base_a_traiter.xlsx')
df.head()
df.info()
df.describe().transpose()
plt.figure(figsize=(12,8))
p= sns.distplot(df['Prix'])
p.set_title("Répartition des différents prix dans les données")
Les prix de billets d'avion sont en très grande majorité entre 0 et 1000 €
fig, axs = plt.subplots(3, 1, figsize=(10,15))
fig.suptitle("Relation entre nos variables quantitatives et le prix du billet d'avion")
test00=df.groupby('Distance',as_index=False).mean()
axs[0].scatter(test00['Distance'], test00['Prix'])
axs[0].set(xlabel='distance entre Paris et la ville de destination', ylabel='Prix selon la distance parcouru')
test01=df.groupby('Duree de vol',as_index=False).mean()
axs[1].scatter(test01['Duree de vol'], test01['Prix'])
axs[1].set(xlabel='Duree du trajet', ylabel='Prix selon la duree du vol')
test02=df.groupby("Total d'escales",as_index=False).mean()
axs[2].scatter(test02["Total d'escales"], test02['Prix'])
axs[2].set(xlabel="Nombre d'escales", ylabel="Prix selon le nombre d'escales durant le trajet")
Selon ces graphiques, nous pouvons constater que :
• il semblerait que la distance qui sépare Paris et la ville de destination ait une influence sur le prix
• La durée du trajet et le nombre d'escales ne semblent pas beaucoup influencer le prix
Dans les prochaines sections nous poussons notre analyse avec la matrice de corrélation et l'analyse en composante principale (PCA)
non_top_10_perc= df.sort_values('Prix', ascending= False).iloc[6133:]
## data sans les données dont le prix était dans les 1% les plus chers
fig, axes = plt.subplots(ncols=2, figsize=(16, 4))
ax1, ax2 = axes
im1 = sns.heatmap(df.corr(), cmap= sns.color_palette("viridis", as_cmap=True), annot = True, ax = ax1)
im2 = sns.heatmap(data=non_top_10_perc.iloc[:, 1:10].corr(), cmap = 'viridis', annot=True, ax = ax2)
im1.set_title("Matrice de corrélation des variables quantitatives")
im2.set_title("Sans les 1% des prix les plus chers")
En éliminant ces valeurs extrêmes on obtient:
• toujours une grande corrélation entre le nombre total d'escales et la durée du vol
• une plus grande corrélation entre la distance et le prix du billet d'avion ce qui est assez intuitif!;
• une corrélation positive mais certes faible entre la distance et le nombre total d'escales ;
• d'une corrélation positive entre la durée du vol et la distance du trajet ce qui est normal;
•d'une faible corrélation positive entre la durée du vol et le prix
•d'une faible corrélation positive entre le nombre total d'escales et le prix
Afin de visualiser en même temps tous nos variables quantitatives( Total d'escales, Duree de vol, Prix, Distance) sur un plan, la solution est d’effectuer une projection orthogonale. Malheureusement, quand on projette des points, on perd de l’information.
C’est ici la clé de l’ACP : rechercher la projection pour laquelle l’inertie des points est maximale.
Nous proposons d'afficher les cercles de corrélation pour regarder quels sont les variables qui sont le plus corrélés avec le prix du billet d'avion.
#Fonctions pour la représentation du cercle de corrélation
def display_circles(pcs, n_comp, pca, axis_ranks, labels=None, label_rotation=0, varsup=None, lims=None):
for d1, d2 in axis_ranks: # On affiche les 2 premières composantes
if d2 < n_comp:
# initialisation de la figure
fig, ax = plt.subplots(figsize=(7,6))
# détermination des limites du graphique
if lims is not None :
xmin, xmax, ymin, ymax = lims
elif pcs.shape[1] < 30 :
xmin, xmax, ymin, ymax = -1, 1, -1, 1
else :
xmin, xmax, ymin, ymax = min(pcs[d1,:]), max(pcs[d1,:]), min(pcs[d2,:]), max(pcs[d2,:])
# affichage des flèches
# s'il y a plus de 30 flèches, on n'affiche pas le triangle à leur extrémité
if pcs.shape[1] < 30 :
plt.quiver(np.zeros(pcs.shape[1]), np.zeros(pcs.shape[1]),
pcs[d1,:], pcs[d2,:],
angles='xy', scale_units='xy', scale=1, color="grey")
# (voir la doc : https://matplotlib.org/api/_as_gen/matplotlib.pyplot.quiver.html)
else:
lines = [[[0,0],[x,y]] for x,y in pcs[[d1,d2]].T]
ax.add_collection(LineCollection(lines, axes=ax, alpha=.1, color='black'))
# affichage des noms des variables
if labels is not None:
for i,(x, y) in enumerate(pcs[[d1,d2]].T):
if x >= xmin and x <= xmax and y >= ymin and y <= ymax :
plt.text(x, y, labels[i], fontsize='14', ha='center', va='center', rotation=label_rotation, color="blue", alpha=0.5)
# affichage du cercle
circle = plt.Circle((0,0), 1, facecolor='none', edgecolor='b')
plt.gca().add_artist(circle)
#variables illustratives
if varsup is not None:
corsup = np.zeros(n_comp)
for j in range(n_comp):
corsup[j] = np.corrcoef(varsup,X_projected[:,j])[0,1]
plt.annotate(varsup.name,(corsup[d1-1],corsup[d2-1]),color='g')
# définition des limites du graphique
plt.xlim(xmin, xmax)
plt.ylim(ymin, ymax)
# affichage des lignes horizontales et verticales
plt.plot([-1, 1], [0, 0], color='grey', ls='--')
plt.plot([0, 0], [-1, 1], color='grey', ls='--')
# nom des axes, avec le pourcentage d'inertie expliqué
plt.xlabel('F{} ({}%)'.format(d1+1, round(100*pca.explained_variance_ratio_[d1],1)))
plt.ylabel('F{} ({}%)'.format(d2+1, round(100*pca.explained_variance_ratio_[d2],1)))
plt.title("Cercle des corrélations (F{} et F{})".format(d1+1, d2+1))
plt.show(block=False)
from sklearn.decomposition import PCA
from sklearn import decomposition
from sklearn.preprocessing import StandardScaler
from sklearn import preprocessing
# choix du nombre de composantes à calculer
n_comp = 2
mycolumns = ["Total d'escales" , 'Duree de vol', 'Distance']
df_pca = df[mycolumns]
# préparation des données pour l'ACP
df_pca = df_pca.fillna(df_pca.mean()) # Il est fréquent de remplacer les valeurs inconnues par la moyenne de la variable
X = df_pca.values
names = df.index #pour avoir les intitulés
#transformation – centrage-réduction
sc = StandardScaler()
Z = sc.fit_transform(X)
# Calcul des composantes principales
acp = PCA(svd_solver='full')
coord = acp.fit_transform(Z)
#vérification
#moyenne
print(np.mean(Z,axis=0))
#écart-type
print(np.std(Z,axis=0,ddof=0))
#Coordonnées de la varaible supplementaire
varsup=df['Prix']
corsup = np.zeros(X.shape[1])
X_projected = acp.transform(Z)
for j in range(X.shape[1]):
corsup[j] = np.corrcoef(varsup,X_projected[:,j])[0,1]
#affichage des corrélations avec les axes
print(corsup)
# Cercle des corrélations
pcs = acp.components_
display_circles(pcs, X.shape[1], acp, [(0,1)],labels = np.array(mycolumns),varsup=df['Prix'])
La distance est bien représentée et positivement corrélée sur l'axe 2. La durée et le total d'escales sont positivement corrélées à l'axe 1 et négativement corrélées à l'axe 2, ils sont aussi mieux répresenter sur l'axe 1 (les flèches sont plus longues sur l'axe 1 que sur l'axe 2).
L'autre point à soulever ici est que les 2 premières dimension contiennent 93% de l'inertie totale (l’inertie est la variance totale du tableau de données, i.e. la trace de la matrice des corrélations)
df_moyen= df.groupby(['Destination']).mean()
df_moyen
df_moyen['Destination']=['Athenes','Londres','Madrid','Moscou','Oslo']
Diagramme à barre des prix moyens de chaque destination
sns.barplot(x="Destination", y="Prix", data=df_moyen)
df_moyen= df.groupby(['Destination']).mean()
df_moyen
df_moyen.loc['Paris']=[0.001,0.001,0.001,0.001]
x = df_moyen.values
min_max_scaler = preprocessing.MinMaxScaler()
x_scaled = min_max_scaler.fit_transform(x)
df_moyen= pd.DataFrame(x_scaled)
df_moyen.columns = ["Total d'escales","Distance","Prix","Duree de vol"]
df_moyen.rename(index={0: 'Athenes',1:'Londres',2:'Madrid',3:'Moscou',4:'Oslo',5:'Paris' }, inplace=True)
df_moyen #On a normalisé les valeursde 0 à 1 avec comme point initial Paris
df_moyen_transposed= df_moyen.T
df_moyen_transposed
Si la toile d'araignée ne s'affiche pas elle est exportée en PNG dans le dossier ('3. DataViz')
fig = make_subplots(rows=1, cols=1, specs=[[{'type': 'polar'}]])
fig.add_trace(go.Scatterpolar(
r = list(df_moyen_transposed['Athenes'])+ [list(df_moyen_transposed['Athenes'])[0]],
theta = list(df_moyen_transposed.index)+["Total d'escales"],
name = "Athènes"
), 1, 1)
fig.add_trace(go.Scatterpolar(
r = list(df_moyen_transposed['Londres'])+ [list(df_moyen_transposed['Londres'])[0]],
theta = list(df_moyen_transposed.index)+["Total d'escales"],
name = "Londres"
), 1, 1)
fig.add_trace(go.Scatterpolar(
r = list(df_moyen_transposed['Madrid'])+ [list(df_moyen_transposed['Madrid'])[0]],
theta = list(df_moyen_transposed.index)+["Total d'escales"],
name = "Madrid"
), 1, 1)
fig.add_trace(go.Scatterpolar(
r = list(df_moyen_transposed['Moscou'])+ [list(df_moyen_transposed['Moscou'])[0]],
theta = list(df_moyen_transposed.index)+["Total d'escales"],
name = "Moscou"
), 1, 1)
fig.add_trace(go.Scatterpolar(
r = list(df_moyen_transposed['Oslo'])+ [list(df_moyen_transposed['Oslo'])[0]],
theta = list(df_moyen_transposed.index)+["Total d'escales"],
name = "Oslo"
), 1, 1)
#fig.show()
fig.write_image('Polar_Destinations.png')
df['Mois'] = df['Date_aller'].apply(lambda date:date.month)
df['Semaine'] = df['Date_aller'].apply(lambda date:date.week)
fig, axes = plt.subplots(ncols=2, figsize=(16, 4))
ax1, ax2 = axes
im1 = df.groupby('Mois').mean()['Prix'].plot(ax = ax1, title = "Evolution du prix en fonction du mois")
im2 = df.groupby('Semaine').mean()['Prix'].plot(ax = ax2,title = "Evolution du prix en fonction des semaines" )
df_compagnie= df.groupby(['Compagnie']).mean()
df_compagnie= df_compagnie.sort_values(by = 'Prix')
df_compagnie['Compagnie']=list(df_compagnie.index)
sns.barplot(x="Compagnie", y="Prix", data=df_compagnie[:5])